"""
@author: tk
@file: 2.9作业.py
@time: 2023/2/9 18:59
"""
# python
# 1、python解释器有哪些？ cpython和pypy的区别是什么？
python基础的解释器类型：CPython、IPython、PyPy、Jython、IronPython等。

Cpython，这个解释器是用C语言开发的，所以叫 CPython在命名行下运行python，就是启动CPython解释器，CPython是使用最广的Python解释器。
PyPy是另一个Python解释器，它的目标是执行速度，PyPy采用JIT技术，对Python代码进行动态编译，所以可以显著提高Python代码的执行速度。
Cython是提前编译，pypy是运行时编译。
Cython完全兼容CPython API，支持很多库，pypy不保证兼容所有

# 2、python2和python3的区别是什么？列举出7个
1.. Python3 对 Unicode 字符的原生支持。
Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类型 str 和 unicode，Python3 只支持 unicode 的 string。
2. Python3 采用的是绝对路径的方式进行 import
Python2 中相对路径的 import
3. Python2 中存在老式类和新式类的区别，Python3 统一采用新式类。
4.Python3 使用更加严格的缩进。
Python2 的缩进机制中，1 个 tab 和 8 个 space 是等价的，所以在缩进中可以同时允许 tab 和 space 在代码中共存。
5.浮点数除法操作符“/”和“//”的区别
“/”
Python2：若为两个整形数进行运算，结果为整形，但若两个数中有一个为浮点数，则结果为浮点数；
Python3:为真除法，运算结果不再根据参加运算的数的类型。
“//”
Python2：返回小于除法运算结果的最大整数；从类型上讲，与"/"运算符返回类型逻辑一致。
Python3：和 Python2 运算结果一样。
6.异常抛出和捕捉机制区别
Python2
raise IOError, "file error" #抛出异常
except NameError, err: #捕捉异常
Python3
raise IOError("file error") #抛出异常
except NameError as err: #捕捉异常
7.比较操作符区别
Python2中任意两个对象都可以比较
11 < 'test' #True
Python3中只有同一数据类型的对象可以比较
11 < 'test' # TypeError: unorderable types: int() < str()


# 3、python中list和set的区别是什么
list是一个集合，在Python中List中的元素用中括号[]来表示list是有序的内容可重复，通过序号访问。
set也是一组数，无序，内容又不能重复，通过调用set()方法创建。set的计算效率比list高。

# 4、python装饰器用来做什么？写过什么装饰器？两层装饰器和三层装饰器区别
# 装饰器可以装饰哪些内容
装饰器在不改变原代码的基础上为代码添加功能

写过计算程序运行时间的装饰器，统计程序运行次数的装饰器等

自身不传入参数的装饰器,使用两层函数定义
自身传入参数的装饰器,使用三层函数定义

装饰器可以装饰函数、方法和类

# 5、python的list底层使用什么实现，怎么实现扩容，字典底层原理
Python 的list底层由结构体实现,列表实现可以是数组和链表。
扩容是指解释器在添加元素时发现容量不够的时候才会扩容，将会重新申请内存,扩容采取翻倍的形式,每一次扩容容量乘以2
字典底层通过哈希表（散列表）实现，是一种关联数组，数组的索引通过哈希函数处理得到散列值将数组关联起来。所以底层是无序的。

# 6、yiled关键字有什么作用，迭代器有什么作用，生成器的使用场景有哪些
生成器内部的代码执行到yield会返回，返回的内容为yield后的表达式。
迭代器可以看作是一个特殊的对象，每次调用该对象时会返回自身的下一个元素
由于可以使用生成器很方便地实现一个迭代器，因此迭代器适用的场景生成器几乎都适用.生成器是特殊的迭代器

# 7、异常捕获主要用在哪些地方，有什么用，使用语句结构， 常见的异常类有哪些
捕获异常try..except..else
异常捕获用在代码不确定是否能执行的地方，可以判断错误，使用的语句为try,except,else
常见的异常有：
AssertionError：当assert断言条件为假的时候抛出的异常
AttributeError：当访问的对象属性不存在的时候抛出的异常
IndexError：超出对象索引的范围时抛出的异常
KeyError：在字典中查找一个不存在的key抛出的异常
NameError：访问一个不存在的变量时抛出的异常
OSError：操作系统产生的异常
SyntaxError：语法错误时会抛出此异常
TypeError：类型错误，通常是不通类型之间的操作会出现此异常
ZeroDivisionError：进行数学运算时除数为0时会出现此异常
# 8、变量名的解析按照什么顺序
LEGB法则：当在函数中使用未确定的变量名时，Python 搜索 4 个作用域：
本地作用域（Loacl），之后是上一层嵌套结构中 def 或 lambda 的本地作用域（Enclosing function locals），
之后是全局作用域（Global），最后是内置作用域（Build-in）。
按这个查找原则，在第一处找到的地方停止。如果没有找到，Python 会报错。也就是说python会从本地变量开始自下向上一层一层的查找所用到的变量

# 9、python的模块查找顺序是什么， 相对导入和绝对导入区别在哪里
查找顺序：
1、先从内存中找
2、再从内置模块中找
3、最后从sys.path中找（环境变量）一定要分清楚谁是执行文件谁是被导入文件
sys返回的是一个列表，里面放了一些文件的路径，但是第一个路径永远是文件所在的文件夹
py文件的文件名不应该与模块名(内置的、第三方的)冲突

绝对导入必须依据执行文件所在的文件夹路径为准
绝对导入无论在执行文件中还是被导入文件中都是适用的
相对导入不能在执行文件中使用
相对导入只能在被导入的模块中使用，使用相对导入，就不需要考虑执行文件到底是谁了，只需要直到模块与模块之间路径的关系
# 10、__name__变量值是什么，有什么用？ __file__变量存储什么内容
__name__是内置变量   __name__变量设置为具有“__main__”的值；如果此文件是从另一个模块导入的，则__name__将设置为模块的名称。
__file__是从中加载模块的文件的路径名(如果它是从文件加载的)。
__file__对于静态链接到解释器的C模块，该属性不存在。对于从共享库动态加载的扩展模块，它是共享库文件的路径名。
# 11、什么是魔术方法？使用过什么魔术方法？
在Python中，所有以双下划线__包起来的方法，统称为Magic Method（魔术方法）
它是一种的特殊方法，普通方法需要调用，而魔术方法不需要调用就可以自动执行。

使用过的魔术方法__init__、__new__、__del__等
# 12、面向对象 python3使用什么继承算法？
c3算法:首先将自身加入到序列,然后对继承序列的元素依次判断
若某元素不在其它序列或者他是所有继承序列的第一个,那么就把这个元素提取到本序列
# 13、打包过python模块包吗？ 有没有去了解过如何打包python模块
怎么打包模块：
创建一个自定义包,然后在包下面
必须要定义__init__.py,还可以加其他模块也可以不加
1.模块一定要写在文件夹里，并在其中包含__init__.py来标识这是一个模块，不然打包会出错。
2.在__init__.py使用__all__ = ["compute"]将需要暴露的接口明确。
3.在包内的模块中导入其他模块，使用 . 表示相对路径。

在自定义模块的同级目录下可以编写一个setup.py文件
生成打包文件 python setup.py sdist
导入自定义模块 pip install dist/my_package-0.1.tar.gz
验证 打开python console，导包验证：

# 14、python中如何使用正则表达式，怎么表示空行，怎么表示以#开头的行？
python中使用正则表达式需要用到re模块

# 表示空行
import re
name1 = "1234"
ret = re.match("^$", name1)
if ret:
    print("1")
else:
    print("2")

# 表示#开头
name1 = "1234"
ret = re.match("^#", name1)
if ret:
    print("1")
else:
    print("2")

# "hello world", "test123 sc"  如何将这里面的单词字符挨个提取出来，引号包裹的算一个单词字符
while 1:
    s1 = input("你想输入的字符串：")
    s2 = "test123 sc"
    l1 = []
    for i in s1:
        if i.isalpha():
            l1.append(i)

    print(l1)
# 15、使用python实现队列

class Queue():
    def __init__(self, array = None):
        self.array = array

    def length(self):
        if not self.array:
            return 0
        else:
            return len(self.array)

    def is_Empty(self):
        return self.array == None

    def push(self, value):
        self.array.append(value)

    def pop(self):
        self.array.pop(0)

    def top(self):
        return self.array[0]

    def travel(self):
        print(self.array)


# 16、使用python实现tree命令
import os
import os.path


def tree(path, depth=0):
    if depth == 0:
        print(path)
    items = os.listdir(path)  #所有的文件夹和文件名 相当于ls
    for item in items:
        # 输出文件夹中的文件和子文件夹名
        print('|    ' * depth, end='') #|乘以深度间隔  end取消换行符
        print('|----', item)
        item = os.path.join(path, item)  #组成下一个路径
        if os.path.isdir(item):  #判断是不是文件夹
            # 递归遍历子目录
            tree(item, depth + 1) #是,就再来一遍上面的操作


tree(r"D:\Downloads\pycharm\pycharm_compute")

# 17、爬取新浪官网的图片
import requests
result = requests.get("https://n.sinaimg.cn/eladies/crawl/513/w550h763/20230207/dccb-24eecb5df5adf448ce01c40b99c6c0de.jpg")
print(dir(result))
print(result.content)
with open("picture.jpg","wb") as fp:
    fp.write(result.content)

# 18、python的内存管理，深浅拷贝的区别
内存管理：以引用计数为主,分代回收和标记清除为辅的回收方式

只有容器里包可变数类型的时候深浅拷贝才会造成不同的影响:
copy()浅拷贝只是拷贝地址,容器所储存的地址还是同一个,只是容器自身的地址不一样
深拷贝会拷贝每一层的值,新创建一个存储地址
# 19、python中文件操作？如何删除文件，创建文件，写入文件，读取文件
删除文件  文件名.truncate()
创建文件  变量名= open("文件名","w+")
写入文件  文件名.write()
读取文件  文件名.read()  文件名.readlines()
# 20、assert关键的作用是什么
assert关键字使您可以测试代码中的条件是否返回True，否则程序将引发AssertionError。可以编写一条代码返回False时输出的消息。
